#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

// reactor类似一个connection容器，核心工作就是：1.管理connection和对应内核事件 2.事件派发
class Reactor
{
    const static int gnum = 64;

public:
    Reactor() : _epoller(std::make_unique<Epoller>()) {}
    void AddConnection(int fd, uint32_t events, const InetAddr &addr, int type)
    {
        // 构建connection
        Connection *conn = new Connection(fd);
        conn->SetEvents(events);
        conn->SetType(type);
        conn->SetReactor(this);
        conn->SetAddr(addr);
        if (conn->Type() == NORMALCONNECTION)
            conn->RegisterHandler(_OnRecver, _OnSender, _OnExcepter);
        else if (conn->Type() == LISTENCONNECTION)
            conn->RegisterHandler(_OnConnection, nullptr, nullptr);

        // 写入epoll
        bool ret = _epoller->AddEvent(fd, events);

        // 托管给_connections
        if (ret != false)
            _connections.insert(std::make_pair(fd, conn));
        else
            delete conn;
    }
    void EnableConnectionReadWrite(int sockfd, bool readable, bool writeable)
    {
        if (!IsConnectionExists(sockfd))
            return;
        uint32_t events = ((readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0) | EPOLLET);
        _connections[sockfd]->SetEvents(events);
        _epoller->ModEvent(sockfd, _connections[sockfd]->Events());
    }
    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revents, gnum, timeout);
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revents[i].data.fd;
            uint32_t rev = _revents[i].events;
            if (rev & EPOLLERR)
                rev |= (EPOLLIN | EPOLLOUT); // 统一读写处理
            if (rev & EPOLLHUP)
                rev |= (EPOLLIN | EPOLLOUT);

            if (rev & EPOLLIN) // 派发写
            {
                if (IsConnectionExists(sockfd) && _connections[sockfd]->_handler_recver)
                {
                    _connections[sockfd]->_handler_recver(_connections[sockfd]);
                }
            }
            if (rev & EPOLLOUT) // 派发读
            {
                if (IsConnectionExists(sockfd) && _connections[sockfd]->_handler_sender)
                {
                    _connections[sockfd]->_handler_sender(_connections[sockfd]);
                }
            }
        }
    }
    void Dispatcher()
    {
        int timeout = -1;
        _isrunning = true;
        while (_isrunning)
        {
            LOG(INFO, "%d connecitons\n", _connections.size());
            LoopOnce(timeout);
            PrintDebug();
        }
        _isrunning = false;
    }
    bool IsConnectionExists(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }
    void SetOnConnection(handler_t OnConnection)
    {
        _OnConnection = OnConnection;
    }
    void SetNormalConnection(handler_t recver, handler_t sender, handler_t excepter)
    {
        _OnRecver = recver;
        _OnSender = sender;
        _OnExcepter = excepter;
    }
    void PrintDebug()
    {
        std::string fdlist;
        for (auto &i : _connections)
        {
            fdlist += std::to_string(i.first) + ' ';
        }
        LOG(DEBUG, "epoll connection list:%s\n", fdlist.c_str());
    }
    void DelConnection(int sockfd)
    {
        if (!IsConnectionExists(sockfd))
            return;
        EnableConnectionReadWrite(sockfd, false, false);
        auto it = _connections.find(sockfd);
        // 2. 从epoll移除事件
        if(_epoller->DelEvent(sockfd)==false)
        {
            LOG(ERROR, "del event error\n");
            exit(1);
        }

        // 3. 仅从迭代器中获取一次指针（后续不再访问map）
        Connection *conn = it->second;

        // 4. 先从map中删除键值对（迭代器失效，避免后续误操作）
        _connections.erase(it);

        // 5. 关闭+释放（此时map已无该条目，指针唯一且安全）
        conn->Close();
        delete conn;
        conn = nullptr;

        LOG(INFO, "%d sockfd quit over,now connections:%d\n", sockfd,_connections.size());
    }
    ~Reactor() {}

private:
    std::unordered_map<int, Connection *> _connections;
    std::unique_ptr<Epoller> _epoller;
    bool _isrunning = false;
    struct epoll_event _revents[gnum];

    // 添加方法集 连接，IO，异常
    handler_t _OnConnection;
    handler_t _OnRecver;
    handler_t _OnSender;
    handler_t _OnExcepter;
};
